﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Reflection;
using PDX.Services;

namespace PDX.ContextManagement
{
    /// <summary>
    /// Default <see cref="IPropertyModel"/>
    /// </summary>
    public class DefaultPropertyModel : IPropertyModel
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DefaultPropertyModel"/> class.
        /// </summary>
        public DefaultPropertyModel()
        {
            Ext = new PropertyModelAspectCollection();
            PropertyType = typeof(object);
        }

        /// <summary>
        /// Gets or sets the getter.
        /// </summary>
        /// <value>
        /// The getter.
        /// </value>
        public Func<object> Getter { get; set; }

        /// <summary>
        /// Gets or sets the setter.
        /// </summary>
        /// <value>
        /// The setter.
        /// </value>
        public Action<object> Setter { get; set; }

        /// <summary>
        /// Gets or sets the value of the property.
        /// </summary>
        /// <value>
        /// The value.
        /// </value>
        public object Value
        {
            get
            {
                if (Getter == null)
                {
                    return System.Windows.Data.Binding.DoNothing;
                }
                return Getter();
            }
            set
            {
                if (Setter != null)
                {
                    Setter(value);
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether the property is readonly.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if the property is readonly; otherwise, <c>false</c>.
        /// </value>
        public bool IsReadonly
        {
            get { return Setter != null; }
        }

        /// <summary>
        /// A dictionary that allows the attaching of various bindable aspects.
        /// </summary>
        public PropertyModelAspectCollection Ext { get; private set; }

        /// <summary>
        /// Gets the display name.
        /// </summary>
        public string DisplayName { get; set; }

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        /// <summary>
        /// Checks if the property has changed
        /// </summary>
        public void CheckPropChanged()
        {
            // TODO should not raise if it hasn't changed?
            // But it's working just fine as is...
            PropertyChanged(this, new PropertyChangedEventArgs("Value"));
        }


        /// <summary>
        /// Gets the type of the property.
        /// </summary>
        /// <value>
        /// The type of the property.
        /// </value>
        public Type PropertyType { get; set; }
    }
}
